/*
 * UserInterface.cpp
 *
 *  Created on: 28.04.2009
 *      Author: h3llfire
 */

#include <wx/aboutdlg.h>
#include "UserInterface.h"
#include "../../core/Impp.h"
#include "Icons.h"
#include "FirstRunWizard.h"
#include "../StdBuddyListModule/BuddyList.h"
#include "../../Version.h"
#include "wx/choicdlg.h"
#include <wx/artprov.h>

#ifdef __WXGTK__
	#include <gtk/gtk.h>
#endif

namespace Impp {

IMPLEMENT_DYNAMIC_CLASS(StdUserInterfaceModule, iUserInterface)

UserInterface::UserInterface(){
	icons = new Icons();

	buddyMenu = new CustomMenu();
	buddyMenu->SetNextHandler(this);
	mainMenu = new CustomMenu();
	mainMenu->SetNextHandler(this);

	Impp* impp = Impp::exemplar();
	impp->Connect(EVT_IMPP_COMMAND, ImppCommandEventHandler(UserInterface::onImppCommand), NULL, this);

	#ifdef __WXGTK__
		icons->registerActionIcon(STD_USERINTERFACE_MODULE_NAME_MAIN, STD_USERINTERFACE_MODULE_ACTION_MAIN_ABOUT, wxArtProvider::GetBitmap(wxT(GTK_STOCK_ABOUT), wxART_MENU, wxSize(-1,-1)));
		icons->registerActionIcon(STD_USERINTERFACE_MODULE_NAME_MAIN, STD_USERINTERFACE_MODULE_ACTION_MAIN_EXIT, wxArtProvider::GetBitmap(wxT(GTK_STOCK_CLOSE), wxART_MENU, wxSize(-1,-1)));
		icons->registerActionIcon(STD_USERINTERFACE_MODULE_NAME_MAIN, STD_USERINTERFACE_MODULE_ACTION_MAIN_EXIT, wxArtProvider::GetBitmap(wxT(GTK_STOCK_PREFERENCES), wxART_MENU, wxSize(-1,-1)));
	#endif
}

UserInterface::~UserInterface(){}


void UserInterface::moduleInit(){
	reigsterBuddyMenuEntryAdder(STD_USERINTERFACE_MODULE_NAME_BUDDY, UserInterface::addStdBuddyMenuEntries);
	reigsterMainMenuEntryAdder(STD_USERINTERFACE_MODULE_NAME_MAIN, UserInterface::addStdMainMenuEntries);
}

void UserInterface::moduleDestroy(){
	delete icons;
}

void UserInterface::buildChooseStatusMenu(wxMenu* menu, Account* account, bool invisible){

	wxLogDebug(wxT("Account id: %i Privacy is: %i"), account->id.ToLong(), Impp::exemplar()->getPrivacySettings(account->id));


	menu->SetTitle(wxT("Status"));

	Status supportedMask = account->protocol->getSupportedStatusMask();

	if(supportedMask == ONLINE){
		addStatusMenuItem(menu,ID_STATUS_ONLINE,(invisible ? ONLINE|INVISIBLE : ONLINE));
	}
	if(supportedMask == FREE4CHAT){
		addStatusMenuItem(menu,ID_STATUS_FREE4CHAT,(invisible ? FREE4CHAT|INVISIBLE : FREE4CHAT));
	}
	if(supportedMask == AWAY){
		addStatusMenuItem(menu,ID_STATUS_AWAY,(invisible ? AWAY|INVISIBLE : AWAY));
	}
	if(supportedMask == OCCUPIED){
		addStatusMenuItem(menu,ID_STATUS_OCCUPIED,(invisible ? OCCUPIED|INVISIBLE : OCCUPIED));
	}
	if(supportedMask == DND){
		addStatusMenuItem(menu,ID_STATUS_DND,(invisible ? DND|INVISIBLE : DND));
	}
	if(supportedMask == NA){
		addStatusMenuItem(menu,ID_STATUS_NA,(invisible ? NA|INVISIBLE : NA));
	}
	if(supportedMask == OFFLINE){
		addStatusMenuItem(menu,ID_STATUS_OFFLINE,OFFLINE);
	}

	wxMenu* xstatus = new wxMenu();

	int xstatusCount = account->protocol->getExtraStatusCount();

	for (int i = 0; i <= xstatusCount; ++i) {
		Status tmp;
		tmp.setExtraStatus(i);
		wxMenuItem* item = new wxMenuItem(xstatus,ID_STATUS_EXTENDED_START + i,account->protocol->getExtraStatusName(i));
		if(i!=0){
			item->SetBitmap(icons->getStatusIcon(tmp));
		}
		xstatus->Append(item);
	}


	wxMenu* visibility = new wxMenu();
	visibility->AppendRadioItem(ID_STATUS_VISIBLE,wxT("Visible"));
	visibility->AppendRadioItem(ID_STATUS_INVISIBLE,wxT("Invisible"));
	visibility->Check(ID_STATUS_VISIBLE, !invisible);
	visibility->Check(ID_STATUS_INVISIBLE, invisible);

	menu->AppendSubMenu(xstatus,wxT("XStatus"));
	menu->AppendSubMenu(visibility,wxT("Visibility"));
}

void UserInterface::buildBuddyMenu(wxMenu* menu, Buddy* buddy){
	buddyMenu->buildMenu(menu, buddy, 0);
}
void UserInterface::buildGroupMenu(wxMenu* menu, Group* group){

}
void UserInterface::buildMainMenu(wxMenu* menu){
	mainMenu->buildMenu(menu, NULL, 0);
}

void UserInterface::onImppCommand(ImppCommandEvent & event){

	wxString moduleName = event.getModuleName();
	wxString actionName = event.getActionName();

	if(moduleName == STD_USERINTERFACE_MODULE_NAME_BUDDY){ //BUDDY MENU

		Buddy* buddy = event.getBuddy();

		if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_CHECK_STATUS){ //check status
			Impp::exemplar()->checkBuddyStatus(buddy);
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_RENAME){ //rename

			iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();

			if(bl == NULL){
				wxLogError(wxT("UserInterface::Could not show Rename Dialog, no Buddylist found!"));
				return;
			}

			wxTextEntryDialog dialog(bl->getWindow(), wxString(wxT("Enter the new Name:")), wxString(wxT("Raname ")),buddy->getCustomName(), wxOK | wxCANCEL);

		    if (dialog.ShowModal() == wxID_OK)
		    {
		    	wxString newName = dialog.GetValue();
		    	Impp::exemplar()->changeBuddyCustomName(buddy,newName);
		    }
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_ALLWAYS_VISIBLE){ //allwasy visible
			if(event.IsChecked()){
				Impp::exemplar()->changeAddToPrivacyList(buddy, BUDDY_PRIVACY_VISIBLELIST);
			}else{
				Impp::exemplar()->changeRemoveFromPrivacyList(buddy, BUDDY_PRIVACY_VISIBLELIST);
			}
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_ALLWAYS_INVISIBLE){ //allways invisbile
			if(event.IsChecked()){
				Impp::exemplar()->changeAddToPrivacyList(buddy, BUDDY_PRIVACY_INVISIBLELIST);
			}else{
				Impp::exemplar()->changeRemoveFromPrivacyList(buddy, BUDDY_PRIVACY_INVISIBLELIST);
			}
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_IGNORE){ //ignore
			if(event.IsChecked()){
				Impp::exemplar()->changeAddToPrivacyList(buddy, BUDDY_PRIVACY_IGNORED);
			}else{
				Impp::exemplar()->changeRemoveFromPrivacyList(buddy, BUDDY_PRIVACY_IGNORED);
			}
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_PRIORITY_HIGH){ //Priority High
			Impp::exemplar()->changeBuddyPriority(buddy, BUDDY_PRIORITY_HIGH);
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_PRIORITY_NORMAL){ //Priority Normal
			Impp::exemplar()->changeBuddyPriority(buddy, BUDDY_PRIORITY_NORMAL);
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_BUDDY_PRIORITY_LOW){ //Priority Low
			Impp::exemplar()->changeBuddyPriority(buddy, BUDDY_PRIORITY_LOW);
		}else if (actionName.StartsWith(wxT("moveToGroup"))){ //move to group
			wxString id = actionName;
			id.Replace(wxT("moveToGroup"), wxEmptyString);
			long int idi;
			id.ToLong(&idi);

			std::vector<Group*> groups = Impp::exemplar()->getAllGroups();
			for (size_t i = 0; i < groups.size(); ++i) {
				if(groups[i]->getId() == idi){
					Impp::exemplar()->changeBuddyGroup(buddy,groups[i]);
					return;
				}
			}
		}
	}else if(moduleName == STD_USERINTERFACE_MODULE_NAME_MAIN){
		if(actionName == STD_USERINTERFACE_MODULE_ACTION_MAIN_ABOUT){
		    wxAboutDialogInfo info;
		    info.SetName(wxT(ABOUT_NAME));
		    wxString version;
		    version << MAJOR_VERSION;
		    version << wxT(".");
		    version << MINOR_VERSION;
		    info.SetVersion(version);
		    wxString description = wxT("Build Date: ");
		    description << wxT(BUILD_DATE);
		    info.SetDescription(description);
		    info.SetCopyright(_T("(C) 2008 Oliver Schneider <oliverschneider89@googlemail.com>"));

		    wxAboutBox(info);
		}else if(actionName == STD_USERINTERFACE_MODULE_ACTION_MAIN_EXIT){
			Impp::exemplar()->close();
		}
	}else{
		event.Skip();
	}



}


void UserInterface::addStatusMenuItem(wxMenu* menu, int id, Status status){
	wxMenuItem* item = new wxMenuItem(menu,id,statusToString(status));
	item->SetBitmap(icons->getStatusIcon(status));
	menu->Append(item);
}

bool UserInterface::showFirstRunWizzard(){

	FirstRunWizard* wiz = new FirstRunWizard();
	bool succses = wiz->RunWizard(wiz->getFirstPage());
	if(succses){
		return true;
	}else{
		return false;
	}
}

void UserInterface::reigsterBuddyMenuEntryAdder(const wxString & moduleName, addBuddyMenuItemCallback callback)
{
	buddyMenu->reigsterMenuEntryAdder(moduleName,(addMenuItemCallback)callback);
}

void UserInterface::reigsterMainMenuEntryAdder(const wxString & moduleName, addMenuItemCallback callback){
	mainMenu->reigsterMenuEntryAdder(moduleName,(addMenuItemCallback)callback);
}

void wxCALLBACK UserInterface::addStdBuddyMenuEntries(iMenu* menu, Buddy* buddy){

	Account* buddyAcc = Impp::exemplar()->getAccount(buddy->getAccountId());
	bool isActive = false;
	bool isConnected = false;
	if(buddyAcc != NULL){
		isActive = buddyAcc->isActive();
		isConnected = buddyAcc->protocol->getConnectionState() == CONNECTION_STATE_CONNECTED;
	}


	//Check invisible
	if(isConnected){
		menu->appendItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_CHECK_STATUS, wxT("Check Real Status"), 90, wxT("The Status of the Buddy is unknown or the buddy is maybe Invisible"));
	}
	//menu->AppendSeparator();

	//Rename
	menu->appendItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_RENAME, wxT("Rename"), 120, wxT("Rename Buddy"));


	iMenu* moveBuddy = menu->appendOrGetSubMenu(STD_USERINTERFACE_MODULE_ACTION_BUDDY_SUBMENU_MOVE, wxT("Move To Group"), 150, wxT("Move To Group"));


	std::vector<Group*> groups = Impp::exemplar()->getAllGroups();
	for (size_t i = 0; i < groups.size(); ++i) {
		if(groups[i]->getId() != buddy->getGroup()->getId()){

			moveBuddy->appendItem(wxString::Format(wxT("moveToGroup%i"), groups[i]->getId().ToLong()), groups[i]->getName(), i, wxT("Move Buddy"));
		}
	}

	//Visibility

	iMenu* visibility = menu->appendOrGetSubMenu(STD_USERINTERFACE_MODULE_ACTION_BUDDY_SUBMENU_VISIBILITY, wxT("Visibility"), 200, wxT("Privaccy Settings for this Buddy"));

	visibility->appendCheckItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_ALLWAYS_VISIBLE, wxT("Always Visible"), buddy->isOnPrivacyList(BUDDY_PRIVACY_VISIBLELIST), 10, wxT("Visible even your are invisible"));
	visibility->appendCheckItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_ALLWAYS_INVISIBLE, wxT("Always Invisible"), buddy->isOnPrivacyList(BUDDY_PRIVACY_INVISIBLELIST), 20, wxT("Invisible even if you are online"));

	menu->appendCheckItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_IGNORE, wxT("Ignore Buddy"),  buddy->isOnPrivacyList(BUDDY_PRIVACY_IGNORED), 210, wxT("Ignore this Buddy"));


	iMenu* priority = menu->appendOrGetSubMenu(STD_USERINTERFACE_MODULE_ACTION_BUDDY_SUBMENU_PRIORITY, wxT("Priority"), 220, wxT("Priority for this Buddy"));

	BuddyPriority buddyPriority = buddy->getPriority();

	priority->appendCheckItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_PRIORITY_HIGH, wxT("High"),buddyPriority == BUDDY_PRIORITY_HIGH, 10, wxT("High"));
	priority->appendCheckItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_PRIORITY_NORMAL, wxT("Normal"),buddyPriority == BUDDY_PRIORITY_NORMAL, 10, wxT("Normal"));
	priority->appendCheckItem(STD_USERINTERFACE_MODULE_ACTION_BUDDY_PRIORITY_LOW, wxT("Low"),buddyPriority == BUDDY_PRIORITY_LOW, 10, wxT("Low"));

}

Account* UserInterface::showChooseAccountDialog(const wxString & title, const wxString & description){
    std::vector<Account*> accounts;
    Impp::exemplar()->getActiveAccounts(accounts);
    Account* acc = NULL;

	wxString* choices = new wxString[accounts.size()];

	for(size_t i = 0; i < accounts.size(); i++){
		Account* acc = accounts[i];
		choices[i] = wxString::Format(wxT("%s (%s)"), acc->self->getCustomName().c_str(), acc->self->getScreenName().c_str());
	}

	{//new scope so the account is delete before the array
		iBuddyList* bl = Impp::exemplar()->getModuleManager()->getBuddyListModule();
		wxWindow* parent = NULL;
		if(bl != NULL){
			parent = bl->getWindow();
		}

	    wxSingleChoiceDialog dialog(parent, wxT("Import to Account:"), wxT("Choose Account"), accounts.size(), choices);

	    if (dialog.ShowModal() == wxID_OK){
	    	acc = accounts[dialog.GetSelection()];
		}
	}
	delete[] choices;
	return acc;
}

void wxCALLBACK UserInterface::addStdMainMenuEntries(iMenu* menu, void* userData){
	menu->appendItem(STD_USERINTERFACE_MODULE_ACTION_MAIN_ABOUT, wxT("About"), 10, wxT("About Impp"));
	menu->appendItem(STD_USERINTERFACE_MODULE_ACTION_MAIN_EXIT, wxT("Exit"), 200, wxT("Exit Impp"));
}

iIcons* UserInterface::getIcons(){
	return icons;
}

}

